package com.fh.shop.api.member.biz;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fh.shop.api.common.ResponseEnum;
import com.fh.shop.api.common.ServerResponse;
import com.fh.shop.api.common.SystemConst;
import com.fh.shop.api.member.mapper.IMemberMapper;
import com.fh.shop.api.member.param.EditPasswordParam;
import com.fh.shop.api.member.param.LoginParam;
import com.fh.shop.api.member.param.MemberParam;
import com.fh.shop.api.member.po.Member;
import com.fh.shop.api.member.vo.MemberVo;
import com.fh.shop.api.mq.message.MailMessage;
import com.fh.shop.api.mq.product.MailProducer;
import com.fh.shop.api.util.*;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Base64;
import java.util.UUID;

@Service("memberService")
@Transactional(rollbackFor = Exception.class)
public class IMemberServiceImpl implements IMemberService {

    @Resource
    private IMemberMapper memberMapper;
    @Autowired
    private MailUtil mailUtil;
    @Autowired
    private MailProducer mailProducer;
    @Value("${mail.active.member.title}")
    private String mailTitle;
    //注册
    @Override
    public ServerResponse reg(MemberParam memberParam) {
        String confirmPassword = memberParam.getConfirmPassword();
        String smsCode = memberParam.getSmsCode();
        String memberName = memberParam.getMemberName();
        String password = memberParam.getPassword();
        String phone = memberParam.getPhone();
        String nickName = memberParam.getNickName();
        String mail = memberParam.getMail();
        //验证非空
        if (StringUtils.isEmpty(memberName) || StringUtils.isEmpty(password)
                || StringUtils.isEmpty(confirmPassword) || StringUtils.isEmpty(smsCode)
                || StringUtils.isEmpty(mail) || StringUtils.isEmpty(nickName)
                || StringUtils.isEmpty(phone)){
            return ServerResponse.error(ResponseEnum.MEMBER_REG_IS_NULL);
        }
        //手机号的正则验证
        if (!ValidateUtil.isPhone(phone)){
            return ServerResponse.error(ResponseEnum.MEMBER_REG_PHONE_IS_ERROR);
        }
        //邮箱的正则验证
        if (!ValidateUtil.isMail(mail)){
            return ServerResponse.error(ResponseEnum.MAIL_IS_ERROR);
        }
        //密码是否一致
        if (!password.equals(confirmPassword)){
            return ServerResponse.error(ResponseEnum.MEMBER_REG_PASSWORD_MISMATCH);
        }
        //验证短信验证码是否正确
        String code = RedisUtil.get(KeyUtil.buildSMSPhoneKey(phone));
        if (!smsCode.equals(code)){
            return ServerResponse.error(ResponseEnum.MEMBER_REG_SMS_CODE_IS_ERROR);
        }
        //会员名的唯一性
        QueryWrapper<Member> memberQueryWrapper = new QueryWrapper<>();
        memberQueryWrapper.eq("membername",memberName);
        Member member = memberMapper.selectOne(memberQueryWrapper);
        if (member != null){
            return ServerResponse.error(ResponseEnum.MEMBER_REG_NAME_IS_EXIST);
        }
        //手机号的唯一性
        QueryWrapper<Member> phoneQueryWrapper = new QueryWrapper<>();
        phoneQueryWrapper.eq("phone",phone);
        Member phone1 = memberMapper.selectOne(phoneQueryWrapper);
        if (phone1 != null){
            return ServerResponse.error(ResponseEnum.MEMBER_REG_PHONE_IS_EXIST);
        }
        //邮箱的唯一性
        QueryWrapper<Member> mailQueryWrapper = new QueryWrapper<>();
        mailQueryWrapper.eq("mail",mail);
        Member mail1 = memberMapper.selectOne(mailQueryWrapper);
        if (mail1 != null){
            return ServerResponse.error(ResponseEnum.MEMBER_REG_MAIL_IS_EXIST);
        }
        //插入会员数据信息 -- 子类自动转换为父类
        memberMapper.insert(memberParam);
        //给会员发邮件 【接口安全】【jwt:登录才能访问的接口】 【公开的:不登录就能访问,但有一部分需要做安全处理】 【uuid <--> id】
        String uuid = UUID.randomUUID().toString();
        Long id = memberParam.getId();
        //发送邮件，走外网，比较慢
        //mailUtil.sendMail(mail,mailTitle,"<h3>恭喜你注册成功，请<a href='http://localhost:8082//api/members/active/"+uuid+"'>激活</a>后，进行登录 ！</h3>");
        MailMessage mailMessage = new MailMessage();
        mailMessage.setTo(mail);
        mailMessage.setTitle(mailTitle);
        mailMessage.setContent("<h3>恭喜你注册成功，请<a href='http://localhost:8082//api/members/active/"+uuid+"'>激活</a>后，进行登录 ！</h3>");
        // 给消息中间件发送消息 【非常快】
        mailProducer.sendMailMessage(mailMessage);

        RedisUtil.setEx(KeyUtil.buildActiveKey(uuid),id+"",SystemConst.ACTIVE_UUID_EXPIRE_TIME);
        //马上删除redis中的数据
        RedisUtil.delete(KeyUtil.buildSMSPhoneKey(phone));
        //响应数据
        return ServerResponse.success();
    }


    //登录
    @Override
    public ServerResponse login(LoginParam loginParam) {
        //非空判断
        String memberName = loginParam.getMemberName();
        String password = loginParam.getPassword();
        if (StringUtils.isEmpty(memberName) || StringUtils.isEmpty(password)){
            return ServerResponse.error(ResponseEnum.MEMBER_LOGIN_IS_NULL);
        }
        //会员名是否正确
        QueryWrapper<Member> memberQueryWrapper = new QueryWrapper<>();
        memberQueryWrapper.eq("memberName",memberName);
        Member member = memberMapper.selectOne(memberQueryWrapper);
        if (member == null){
            return ServerResponse.error(ResponseEnum.MEMBER_LOGIN_NAME_ERROR);
        }
        //密码是否正确
        String dbPassword = member.getPassword();
        if (!password.equals(dbPassword)){
            return ServerResponse.error(ResponseEnum.MEMBER_LOGIN_PASSWORD_ERROR);
        }
        //状态是否激活
        Integer status = member.getStatus();
        if (status.intValue() == SystemConst.MEMBER_STATUS_INACTIVE){
            return ServerResponse.error(ResponseEnum.MEMBER_LOGIN_STATUS_ERROR);
        }
        //构建会员信息 从数据库获取信息 member
        MemberVo memberVo = new MemberVo();
        Long memberId = member.getId();
        String nickName = member.getNickName();
        memberVo.setId(memberId);
        memberVo.setNickName(nickName);
        String uuid = UUID.randomUUID().toString();
        memberVo.setUuid(uuid);
        //就java对象 转换为 json格式的字符串
        String memberVoJSON = JSON.toJSONString(memberVo);
        //Base64偏码  字节
        String Base64MemberJSON = Base64.getEncoder().encodeToString(memberVoJSON.getBytes());
        //生成签名
        String sign = Md5Util.sign(memberVoJSON, SystemConst.SECRET);
        //Base64偏码 转换签名
        String base64Sign = Base64.getEncoder().encodeToString(sign.getBytes());
        //将会员信息和签名响应给客户端  x.y  x-代表会员信息 .-代表分隔符 y-代表签名
        String token = Base64MemberJSON +"."+ base64Sign;
        //存入redis，设置过期时间
        RedisUtil.setEx(KeyUtil.buildMemberKey(memberId),uuid,SystemConst.MEMBER_EXPIRE_TIME);
        //响应给客户端
        return ServerResponse.success(token);
    }


    //修改密码
    @Override
    public ServerResponse updatePassword(EditPasswordParam passwordParam) {
        String oldPwd = passwordParam.getOldPwd();
        String newPwd = passwordParam.getNewPwd();
        String confirmPwd = passwordParam.getConfirmPwd();
        //非空判断
        if (StringUtils.isEmpty(oldPwd) || StringUtils.isEmpty(newPwd) || StringUtils.isEmpty(confirmPwd)){
            return ServerResponse.error(ResponseEnum.MEMBER_PWD_IS_NULL);
        }
        //判断新密码和确认密码
        if (!newPwd.equals(confirmPwd)){
            return ServerResponse.error(ResponseEnum.MEMBER_REG_PASSWORD_MISMATCH);
        }
        //验证旧密码是否正确
        Long memberId = passwordParam.getMemberId();
        Member dbMember = memberMapper.selectById(memberId);
        String password = dbMember.getPassword();
        //旧密码与数据库对比
        if (!oldPwd.equals(password)){
            return ServerResponse.error(ResponseEnum.MEMBER_PWD_OLD_IS_MISMATCH);
        }
        //更新密码
        Member member = new Member();
        member.setId(memberId);
        member.setPassword(newPwd);
        memberMapper.updateById(member);
        //注销 - 清空数据
        RedisUtil.delete(KeyUtil.buildMemberKey(memberId));
        return ServerResponse.success();
    }

    //激活会员,发送邮件
    @Override
    public int activeMember(String uuid) {
        String Key = KeyUtil.buildActiveKey(uuid);
        String id = RedisUtil.get(Key);
        if (StringUtils.isEmpty(id)){
            return SystemConst.MEMBER_ACTIVE_ERROR;
        }
        Member member = new Member();
        member.setId(Long.parseLong(id));
        member.setStatus(SystemConst.MEMBER_STATUS_ACTIVE);
        memberMapper.updateById(member);
        //删除缓存
        RedisUtil.delete(Key);
        return SystemConst.MEMBER_ACTIVE_OK;
    }

    // 再次 -- 激活会员
    @Override
    public ServerResponse sendActiveMail(String mail) {
        //邮箱格式是否正确
        if(!ValidateUtil.isMail(mail)){
            return ServerResponse.error(ResponseEnum.MAIL_IS_ERROR);
        }
        //验证邮箱是否存在
        QueryWrapper<Member> memberQueryWrapper = new QueryWrapper<>();
        memberQueryWrapper.eq("mail",mail);
        Member member = memberMapper.selectOne(memberQueryWrapper);
        if (member == null){
            return ServerResponse.error(ResponseEnum.MEMBER_ACTIVE_MAIL_NOT_EXIST);
        }
        //判断是否激活
        Integer status = member.getStatus();
        if (status.intValue() == SystemConst.MEMBER_STATUS_ACTIVE){
            return ServerResponse.error(ResponseEnum.MEMBER_IS_ACTIVE);
        }
        //发送邮件 【没有激活】 uuid <-->id/mail/phone
        String uuid = UUID.randomUUID().toString();
        mailUtil.sendMail(mail,mailTitle,"<h3>恭喜你注册成功，请<a href='http://localhost:8082//api/members/mail/active/"+uuid+"'>激活</a>后，进行登录 ！</h3>");
        RedisUtil.setEx(KeyUtil.buildActiveKey(uuid),mail,SystemConst.ACTIVE_UUID_EXPIRE_TIME);
        return ServerResponse.success();
    }

    // 再次发送邮件 【根据邮箱激活】[方法是多种多样的,效果一样]
    @Override
    public boolean activeMailMember(String uuid) {
        String Key = KeyUtil.buildActiveKey(uuid);
        String mail = RedisUtil.get(Key);
        if (StringUtils.isEmpty(mail)){
            return false;
        }
        Member member = new Member();
        member.setStatus(SystemConst.MEMBER_STATUS_ACTIVE);
        QueryWrapper<Member> memberQueryWrapper = new QueryWrapper<>();
        memberQueryWrapper.eq("mail",mail);
        //更新 状态 -/- 更新的查询条件
        memberMapper.update(member, memberQueryWrapper);
        //删除缓存
        RedisUtil.delete(Key);
        return true;
    }
}
